Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughBUS.ARRIVALS 기반 실시간 도착 API와 Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Bubble as Bubble 컴포넌트
participant Hook as useBusArrivals 훅
participant API as BUS.ARRIVALS API
User->>Bubble: 마운트/렌더
Bubble->>Hook: useBusArrivals(onError?)
Hook->>API: GET /api/bus/arrivals
API-->>Hook: ArrivalsResponse (stops, updatedAt)
Hook-->>Bubble: data 또는 null
Bubble->>Bubble: stopName으로 정류장 필터링(예: 인문관)
Bubble-->>User: 정류장별 버스 목록 및 시간 라벨
Note over Hook: 자동 재요청 주기: 30초 (백그라운드 포함)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~40 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
src/components/Bubble.tsx (1)
24-47: arrivals 의존성으로 7초마다 오버레이 전체 재마운트 가능성 (선택적 리팩터)
useBusArrivals가 7초마다 refetch하면서arrivals객체가 갱신될 때마다 이useEffect가 다시 실행되고, 내부에서clearExisting()→ 새 overlay 생성 흐름이라, 도착 정보가 갱신될 때마다 오버레이가 언마운트/리마운트되는 플리커가 발생할 여지가 있습니다. 체감상 문제가 된다면:
- 오버레이 생성/제거는
stop,onClose만 의존하는 이펙트로 두고,- 내부 내용은 별도 React 컴포넌트로 빼서
arrivals를 props로 넘겨 일반적인 리렌더링만 일어나게 하거나,- 전역(예:
window.__currentBubbleOverlay)에 root를 캐싱해 두고 동일 overlay 위에서만root.render를 다시 호출하는 방향으로 분리해 보면 좋겠습니다. 급한 이슈는 아니라 optional refactor로 봐도 될 것 같습니다.
Also applies to: 270-291
src/api/bus.ts (1)
30-67: 도착 정보 타입/훅 설계는 명확하나, 필요 시 쿼리 활성화 제어 옵션 고려 권장
ArrivalBus/ArrivalStop/ArrivalsResponse로 도착 정보를 명시적으로 모델링하고,useBusArrivals에서ArrivalsResponse | null을 반환하는 구조는 타입 측면에서 깔끔합니다. 다만 현재 구현대로면 Bubble 컴포넌트에서 이 훅을 사용하는 동안(오버레이가 닫혀 있어도) 7초마다 항상 도착 정보 API가 호출될 수 있습니다.향후 트래픽이나 성능 이슈가 보이면:
useBusArrivals(enabled: boolean, onError?: ...)처럼enabled플래그를 인자로 받게 하고,- 내부
useQuery에enabled옵션을 전달하거나,- 혹은 쿼리 키에 정류장 정보 등을 포함해 필요한 경우에만 구독하도록
조정할 수 있도록 설계 여지를 열어 두는 것도 좋을 것 같습니다. 지금 단계에서는 선택적 리팩터로 봐도 될 것 같습니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
src/api/bus.ts(2 hunks)src/components/Bubble.tsx(5 hunks)src/contexts/LanguageContext.tsx(4 hunks)src/data/busStops.ts(1 hunks)src/lib/endpoints.ts(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: KwonDeaGeun
Repo: KwonDeaGeun/WhatTheBus-Web PR: 21
File: src/App.tsx:16-23
Timestamp: 2025-09-22T04:45:54.455Z
Learning: KwonDeaGeun은 TypeScript에서 any 타입 사용을 피하고 더 타입 안전한 코드를 선호한다.
🧬 Code graph analysis (2)
src/components/Bubble.tsx (1)
src/api/bus.ts (1)
useBusArrivals(48-67)
src/api/bus.ts (4)
src/lib/api.ts (1)
apiGet(14-22)src/data/bus.ts (1)
Bus(1-6)src/lib/endpoints.ts (1)
API_ENDPOINTS(1-9)src/lib/error.ts (1)
handleApiError(9-49)
🔇 Additional comments (4)
src/contexts/LanguageContext.tsx (1)
20-21: 신규 버스 정류장/도착 상태 번역 키 일관성 양호
busStop.인문관,common.noArrival,common.arrivingSoon모두 데이터(busStops.ts)와 UI(Bubble.tsx) 사용처와 키가 잘 맞고,Record<string, string>으로 any 없이 타입도 유지돼서 i18n 측면에서 무리 없어 보입니다. Based on learningsAlso applies to: 44-46, 56-57, 80-81
src/data/busStops.ts (1)
11-12: 신규 정류장 '인문관' 추가 일관성 OK정류장 이름
"인문관"이 번역 키(busStop.인문관)와 Bubble 컴포넌트의DISPLAY_NAME_MAP키와도 일치해서, 클릭 시 도착 정보 매칭에도 문제 없을 것 같습니다. 좌표만 실제 지도 기준으로 한 번 눈으로만 검증해 두면 좋겠습니다.src/lib/endpoints.ts (1)
2-8: BUS.LOCATION → BUS.ARRIVALS, SHUTTLE.LOCATIONS 구조 변경 확인 필요셔틀 위치(
SHUTTLE.LOCATIONS)와 일반 버스 도착(BUS.ARRIVALS)을 분리한 구조는 명확해서 좋습니다. 다만 예전에 쓰이던API_ENDPOINTS.BUS.LOCATION참조가 남아 있으면 바로 런타임 에러가 날 수 있으니, 레포 전체에서 해당 키가 더 이상 사용되지 않는지 한 번만 검색해서 확인해 주세요.src/api/bus.ts (1)
12-14: 셔틀 위치 조회 엔드포인트 전환 시 응답 스키마 확인 필요
useBusLocations가 이제API_ENDPOINTS.SHUTTLE.LOCATIONS에서Bus[]를 기대하고 있는데, 새 셔틀 API가 정말로 순수 배열을 바로 반환하는지(예:{ data: Bus[] }같은 래퍼 없이) 백엔드 스펙을 한 번만 확인해 주세요. 만약 래퍼 객체로 바뀌어 있다면 현재 구현은Array.isArray(data) ? data : []때문에 조용히 빈 배열로 떨어져 실제 위치가 표시되지 않을 수 있습니다.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
src/api/bus.ts (2)
24-27: 위치(7초)와 도착(30초) refetch 주기 차이가 의도된 설계인지 점검 제안
useBusLocations는 7초,useBusArrivals는 30초로 refetch 주기가 다르게 잡혀 있습니다. 실시간성이 더 중요한 쪽에 맞춘 의도된 값이라면 그대로 두어도 되지만, 둘을 동일 주기로 맞추는 것이 목표였다면 상수로 추출해서 공유하거나 주기를 명시적으로 설명하는 주석을 남겨 두면 유지보수 관점에서 더 명확해질 것 같습니다.
48-67:useBusArrivals의 에러 처리 및 null 처리에 대한 소소한 개선 제안현재
try/catch에서 에러를 모두 처리하고null을 반환하기 때문에 React Query 입장에서는 항상 “성공 + data가 null일 수 있음” 상태가 되고,isError/error는 사용되지 않게 됩니다. 이 패턴을 의도하신 것이라면 괜찮지만, 훅을 소비하는 쪽에서 React Query의 에러 상태를 활용하고 싶다면 onError 콜백 호출 후에 에러를 그대로 throw하는 쪽도 고려해 볼 수 있습니다. 또한,return data || null;보다는
- const data = await apiGet<ArrivalsResponse>( - API_ENDPOINTS.BUS.ARRIVALS - ); - return data || null; + const data = await apiGet<ArrivalsResponse>( + API_ENDPOINTS.BUS.ARRIVALS + ); + return data ?? null;처럼 null 병합 연산자를 사용하면, 혹시나 나중에
ArrivalsResponse가 빈 문자열 같은 다른 falsy 값으로 확장되더라도 의도치 않게 null로 처리되는 일을 막을 수 있어 조금 더 안전합니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/api/bus.ts(2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: KwonDeaGeun
Repo: KwonDeaGeun/WhatTheBus-Web PR: 21
File: src/App.tsx:16-23
Timestamp: 2025-09-22T04:45:54.455Z
Learning: KwonDeaGeun은 TypeScript에서 any 타입 사용을 피하고 더 타입 안전한 코드를 선호한다.
🧬 Code graph analysis (1)
src/api/bus.ts (3)
src/lib/api.ts (1)
apiGet(14-22)src/lib/endpoints.ts (1)
API_ENDPOINTS(1-9)src/lib/error.ts (1)
handleApiError(9-49)
🔇 Additional comments (2)
src/api/bus.ts (2)
12-21: SHUTTLE.LOCATIONS 응답 스키마가Bus[]와 정확히 일치하는지 한 번 더 확인해 주세요
BUS.LOCATION에서API_ENDPOINTS.SHUTTLE.LOCATIONS로 엔드포인트를 바꾸고 그대로apiGet<Bus[]>()를 사용하고 있습니다. 런타임에서는Array.isArray로 방어하고 있지만, 실제 응답이Bus[]인터페이스와 완전히 일치하지 않으면 타입/도메인 불일치가 생길 수 있으니, 백엔드 스펙과 맞는지 한 번만 점검해 보시고 필요하다면 여기에서 매핑/변환 레이어를 두는 편이 더 안전합니다.
30-46: 도착 정보 타입 정의는 명확하지만 null/undefined 케이스만 한 번 더 확인 필요
minutesLeft,remainingSeats를number | null로 정의해 둔 점은 도메인 의미가 잘 드러나서 좋습니다. 다만 백엔드에서 필드를 아예 생략하는 경우가 있다면 런타임 값은undefined가 될 수 있으니, 응답 스펙이 “항상 필드는 존재하지만 값이 없을 때는 null”인지 한 번 더 확인해 보시고, 필요하다면 파싱 단계에서 기본값을 보정해 두는 것도 고려해 볼 만합니다.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
src/utils/mapOverlays.ts (1)
3-3: Shuttle 기반으로 오버레이를 키잉하도록 변경된 점이 타입과 일관적입니다.
Shuttle타입을 도입해createBusOverlays(map, buses: Shuttle[])시그니처와 캐시 키(bus.shuttleId)가 맞춰진 부분 좋습니다.Shuttle.shuttleId가 항상 유효한 값으로 들어온다는 전제가 있다면,${bus.lat}-${bus.lng}fallback 이 실제로 필요한지(또는 assert 로 바꿀지) 한 번 더 정리해 두면 의도가 더 명확해질 것 같습니다.Also applies to: 285-310
src/hooks/useBusSelection.ts (1)
2-2: Shuttle[] 기반 선택 로직으로의 타입 정리가 자연스럽습니다.
buses: Shuttle[]로 바뀌어 위치/방향 필드 사용이 명시적이고, 상위useBusLocations결과와도 타입이 잘 맞습니다.idx = n - 1는 UI에서 항상 1부터 시작하는 입력을 전제로 하므로, 방어적으로1 ≤ n ≤ buses.length범위 체크를 추가해 두면 추후 호출부 변경에도 더 안전할 것 같습니다.Also applies to: 6-6, 11-36
src/types/bus.ts (1)
1-23: 셔틀·도착 정보 타입 정의가 직관적이고 null 가능성이 잘 표현되어 있습니다.API 응답 형태를
Shuttle,ArrivalBus,ArrivalStop,ArrivalsResponse로 구분해 둔 덕분에 각 계층 책임이 명확하고,minutesLeft/remainingSeats의null여부도 타입에서 잘 드러납니다. 나중에 클라이언트 내부 도메인 모델을 더 풍부하게 가져가고 싶다면(예:updatedAt을Date로 파싱한 뷰 모델 등) 이 파일의 원본 응답 타입과 별도의 도메인 타입을 분리해 두는 것도 고려해 볼 만합니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
src/api/bus.ts(2 hunks)src/data/bus.ts(0 hunks)src/hooks/useBusSelection.ts(1 hunks)src/hooks/useMapOverlays.ts(2 hunks)src/types/bus.ts(1 hunks)src/utils/mapOverlays.ts(2 hunks)
💤 Files with no reviewable changes (1)
- src/data/bus.ts
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: KwonDeaGeun
Repo: KwonDeaGeun/WhatTheBus-Web PR: 21
File: src/App.tsx:16-23
Timestamp: 2025-09-22T04:45:54.455Z
Learning: KwonDeaGeun은 TypeScript에서 any 타입 사용을 피하고 더 타입 안전한 코드를 선호한다.
🧬 Code graph analysis (3)
src/hooks/useBusSelection.ts (1)
src/types/bus.ts (1)
Shuttle(1-6)
src/utils/mapOverlays.ts (1)
src/types/bus.ts (1)
Shuttle(1-6)
src/hooks/useMapOverlays.ts (1)
src/types/bus.ts (1)
Shuttle(1-6)
🔇 Additional comments (2)
src/hooks/useMapOverlays.ts (1)
3-3: Shuttle 타입으로의 전환이 잘 정리되어 있습니다.버스 데이터 입력을
Shuttle[]로 고정해createBusOverlays시그니처와 일치시키면서 타입 안정성이 올라갔고, 기존 이펙트 로직과 의도도 그대로 유지되어 보입니다.Also applies to: 14-14
src/api/bus.ts (1)
5-5: Shuttle 위치/도착 데이터 훅 설계가 타입·엔드포인트와 잘 정합됩니다.
useBusLocations가 항상Shuttle[]를(비정상 응답/에러 시에도[]) 반환하고,useBusArrivals가ArrivalsResponse | null을 반환하도록 한 패턴이 명확해서 호출부에서 분기 처리하기 좋아 보입니다. 다만 소비 측(예: Bubble 컴포넌트)에서data === null(호출 실패)과data.stops.length === 0(정상 호출 + 데이터 없음)을 어떻게 구분할지 한 번 더 확인해 두면 UX 측면에서 의도된 상태 표현을 보장할 수 있을 것 같습니다.Also applies to: 12-22, 32-50
Summary by CodeRabbit
신기능
데이터/지역화
잡무
✏️ Tip: You can customize this high-level summary in your review settings.